今天所要介紹的是物件導向的第一個原則: OCP (Open/Close Principle)
雖然物件導向使用起來非常貼近真實世界的模式,但是他也是有很多原則的。雖然不依照這些原則也是可以使用使用物件導向方式來撰寫程式,只不過開發的時候可能會很開心很順利,但是如果遇到BUG或者需要修改維護,那可能就會很頭痛了。
今天要介紹的是物件導向的第一條原則OCP(Open/Close Principle)開放封閉原則。乍聽之下好像很抽象、也很難懂,其實OCP就是對**”擴展開放**”對”修改封閉”。說更明白一點,就是讓軟體可以更容易的新增其他的功能而不避去修改程式碼!(可以擴展,不能修改的意思)
我以計算二代健保的補充保費來舉例說明(這只是個範例,實際要怎麼計算還是要參考一下健保局的網站喔^_^):
小明常常都會投資股票,他今天想要計算他投資股票股利的補充保費為多少。(假設投資股票股利的補充保費為 0.3%(真正的二代健保好像是2%) )
class 股票 {
public double 股利 { get; set; }
}
保費計算方式為:
double 計算補充保費(股票[] stocks) {
double 補充保費 = 0;
foreach (var stock in stocks) {
補充保費 += (stock.利息 * 0.3);
}
return 補充保費;
}
問題來了,小明因為想多賺一點錢因此就開始兼差,這時候就必須修改程式來符合計算兼差收入的補充保費(假設兼差收入的補充保費為0.2%)
double 計算補充保費(object[] incomes) {
double 補充保費 = 0;
foreach (var income in incomes) {
if (income is 股票) {
股票 stock = (股票)income;
補充保費 += (stock.利息 * 0.3);
} else {
個人收入 person = (個人收入)income;
補充保費 += (person.兼差收入 * 0.2);
}
}
return 補充保費;
}
如果下次又有新的計算方式那豈不是要一直不段的修改程式,如果再不小心一點把原本沒問題的程式改出問題來了,那不就更加難以維護了。所以,以上的程式範例並沒有符合物件導向程式設計的第一條原則: 開放封閉原則(OCP)。
接下來我們來看看如果把上面的範例修改成符合OCP這條原則,是不是會更加的好維護、好使用呢!
首先,因為股利跟兼差都是收入,所以我們先建立一個抽象類別叫做”收入”,並且有一個抽象的方法叫做”補充保費”(因為我們的目的是要計算補充保費,而兼差收入跟股利的補充保費計算方式都不一樣)。
public abstract class 收入 {
public abstract double 補充保費();
}
再來,我們讓”股票收入”與”兼差收入”都去繼承收入這個抽象類別,並且實作補充保費這個抽象方法。
public class 股票收入 : 收入 {
public double 利息 { get; set; }
public override double 補充保費() {
return 利息 * 0.3;
}
}
public class 個人收入 : 收入 {
public double 兼差收入 { get; set; }
public override double 補充保費() {
return 兼差收入 * 0.2;
}
}
最後我們的補充保費計算方就會變得很簡單。
public double 計算補充保費(收入[] incomes) {
double 補充保費 = 0;
foreach (收入 item in incomes) {
補充保費 += item.補充保費();
}
return 補充保費;
}
各位發現了嗎?假設今天有第三種收入,而他的補充保費計算方式與前兩種完全不同,我們是不是只要擴充一個類別(對擴充開放)就可以達到我們的目的-計算補充保費,完全不用去修改任何程式碼(對修改封閉)。
類別、變數名稱為什麼要用中文?
我上面只有類別名稱用中文,變數還是英文喔!!
如果是為了可讀性,為什麼stocks不用中文來表示?
對阿!是因為範例想提高可讀性!不過,如果類別、變數全變中文了看起來很怪,可能是平常不會用中文來寫程式吧!!你覺得呢??